package ace.cmp.spring.data.jdbc.querydsl.core.repository.handler.impl;

import ace.cmp.spring.data.jdbc.querydsl.core.model.PropertyRelation;
import ace.cmp.spring.data.jdbc.querydsl.core.repository.handler.QuerydslLastModifiedDateAnnotationHandler;
import ace.cmp.spring.data.jdbc.querydsl.core.repository.handler.QuerydslNowGenerator;
import ace.cmp.spring.data.jdbc.querydsl.core.util.QuerydslPropertyRelationUtils;
import com.querydsl.core.types.Path;
import com.querydsl.sql.dml.SQLInsertClause;
import com.querydsl.sql.dml.SQLUpdateClause;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.util.Assert;

/**
 * @author caspar
 * @date 2024/6/26 16:03 更新时间注解处理器，用于底层插入数据的时候自动处理字段时间
 */
public class QuerydslLastModifiedDateAnnotationHandlerImpl
    implements QuerydslLastModifiedDateAnnotationHandler {
  private final QuerydslNowGenerator querydslNowGenerator;
  private final QuerydslPropertyRelationUtils querydslPropertyRelationUtils;

  public QuerydslLastModifiedDateAnnotationHandlerImpl(
      QuerydslNowGenerator querydslNowGenerator,
      QuerydslPropertyRelationUtils querydslPropertyRelationUtils) {
    this.querydslPropertyRelationUtils = querydslPropertyRelationUtils;
    this.querydslNowGenerator = querydslNowGenerator;
  }

  @Override
  public void processInsert(
      Object entity, SQLInsertClause sqlClause, boolean enableLastModifiedDateForce) {
    List<PropertyRelation> propertyRelationList = this.getPropertyRelationList(entity);
    if (CollectionUtils.isEmpty(propertyRelationList)) {
      return;
    }
    for (PropertyRelation propertyRelation : propertyRelationList) {
      Object submitValue = querydslPropertyRelationUtils.getValue(entity, propertyRelation);
      // null is 不支持属性类型
      Object generateValue = querydslNowGenerator.generate(propertyRelation);
      Assert.notNull(
          generateValue,
          String.format(
              "the type is not support,entity : %s, field name : %s",
              entity.getClass().getTypeName(), propertyRelation.getField().getName()));
      Object value = submitValue;
      if (value == null || enableLastModifiedDateForce) {
        value = generateValue;
      }

      querydslPropertyRelationUtils.setValue(entity, propertyRelation, value);
      sqlClause.set((Path<Object>) propertyRelation.getPath(), value);
    }
  }

  @Override
  public void processUpdate(
      Object entity, SQLUpdateClause sqlClause, boolean enableLastModifiedDateForce) {
    List<PropertyRelation> propertyRelationList = this.getPropertyRelationList(entity);
    if (CollectionUtils.isEmpty(propertyRelationList)) {
      return;
    }
    for (PropertyRelation propertyRelation : propertyRelationList) {
      Object submitValue = querydslPropertyRelationUtils.getValue(entity, propertyRelation);
      // null is 不支持属性类型
      Object generateValue = querydslNowGenerator.generate(propertyRelation);
      Assert.notNull(
          generateValue,
          String.format(
              "the type is not support,entity : %s, field name : %s",
              entity.getClass().getTypeName(), propertyRelation.getField().getName()));
      Object value = submitValue;
      if (value == null || enableLastModifiedDateForce) {
        value = generateValue;
      }

      querydslPropertyRelationUtils.setValue(entity, propertyRelation, value);
      sqlClause.set((Path<Object>) propertyRelation.getPath(), value);
    }
  }

  private List<PropertyRelation> getPropertyRelationList(Object entity) {
    return this.querydslPropertyRelationUtils
        .getPropertyRelation(entity.getClass(), LastModifiedDate.class)
        .values()
        .stream()
        .collect(Collectors.toList());
  }
}
